In the field of computer science, the term “software”, “code”, or “software code” often refers to a collection of statements and/or declarations written in a programming language to specify actions to be performed by a processing device. The processing device may be a general purpose computer or a dedicated device that is directed to a specific activity or function.
Like any other development process for a complex design, it is important to ensure that the process for developing software involves adequate testing and verification of the performance and functionality of the software. For software in particular, it is quite common during the development process to discover errors or “bugs” in the programming code. Many different types of errors may occur in a software program. For example, such errors can be syntax errors, semantic errors, or logic errors. The syntax error occurs when code is written in a manner not allowed by the rules of the language, and is the one type of error that can be easily caught by a compiler or interpreter.
A semantic error occurs when the syntax of the code is correct, but the semantics or meaning is not what was intended. A logic error occurs when the algorithmic flow of the software does not perform or produce a result that is intended, even if the semantics or syntax of the coding is correct. Because the semantic and logic errors can occur even if the coding obeys the language (syntax) rules, semantic and logic errors cannot typically be identified by the compiler or interpreter. Therefore, a software developer will often need to engage in debugging activities to address errors that are semantic or logic in nature.
The debugging activity is typically performed to allow the programmer or test engineer to observe the run-time behavior of the software program and to determine the location, cause, environment, or effect of the errors. With the debugging process or using a debugging tool, one can examine the content of variables or memory, insert stopping points, and/or step through the execution of the program. Once the cause of the error is identified, the developer can then modify the code to correct the problem.
When an error is encountered in software code, there are two common approaches that are often taken to debug the: (a) the recompilation approach and (b) the interpreter approach.
In the recompilation approach, the erroneous software program is recompiled for debugging purposes, by introducing debugging information into the compiled code. Since, in the interests of maximal time and execution efficiency, the original executable from which the error was discovered is usually formed as compiled optimized executables that do not include debug information, the debug information needs to be added to accomplish the debugging goals of the programmer. This approach, however, is associated with some significant performance problems. First, this approach requires the time and expense of performing a recompilation of the software. In addition, the recompilation in debugging mode typically precludes compilation optimizations from being used in the recompiled code. This means that the recompiled code in debugging mode will execute slower and/or less efficiently than the original compiled code that does include the optimizations.
In the interpreter approach, an interpreter is used to execute the software program. The interpreter is a program that can execute source code directly without compilation, or can use an intermediate representation of the source code for execution purposes. In many cases, the interpreter allows the software to be executed interactively. The main advantage of the interpreter approach over the recompilation approach is that the interpreter approach avoids the time and expense of having to recompile the software code. The disadvantage of this approach is that software execution using an interpreter is usually much, much slower than software execution of compiled software.
Therefore, there is a need for an improved approach for debugging software which can retain the best benefits of the recompilation and interpreter approaches, but without the corresponding drawbacks.